#ifndef __LList_H__
#define __LList_H__

#include "ListIter.h"

template <class T>
class LList
{
  public:
    virtual ~LList();                   //  DTOR
    LList();                            //  CTOR
    LList(const LList& );               //  copy CTOR
    LList& operator=(const LList& );    //  Assigment operator

    class Iterator;         //  nested class Iterator
    class ConstIterator;    //  nested class ConstIterator for preventing changes in data pointed by iterator

    ConstIterator Begin() const;        //  for const list return ConstIterator for not changing data
    ConstIterator End()   const;

    Iterator    Begin();
    Iterator    End();

    Iterator    Insert(ConstIterator , const T*);
    Iterator    Remove(ConstIterator);

    bool        IsEmpty() const;    //  relevant also for const List

  private:
    List* m_list;
};

template <class T>
class LList<T>::Iterator      //  nested class Iterator
{
 public:
    //  ~Iterator();                                    //  use default
    //  Iterator(const Iterator&)                       //  use default
    //  const Iterator& operator=(const Iterator&)      //  use default

//  friend functions for building from private CTOR Iterator
    friend Iterator LList<T>::Begin();
    friend Iterator LList<T>::End();

    Iterator& operator++();
    Iterator& operator--();
    T*  Get() const;                            //  Get also from const Iterator

 private:
    ListIter m_iter;
#ifdef _DEBUG
    List*   m_list;
#endif  //  #ifdef _DEBUG

    Iterator(ListIter
#ifdef _DEBUG           //  in debug mode also another parameter for init the value of poined list
    , List*
#endif  //  #ifdef _DEBUG
                    );      //  private CTOR from ListIter. can only initalize in Begin() or End() methods of LList.
};

/** Decleration of non member functions    **/
//  Boolean operators, works also on Iterator and ConstIterator comparing, use the conversion from Iterator to ConstIterator
template <class T>
bool operator==(const typename LList<T>::ConstIterator&, const typename LList<T>::ConstIterator&);

template <class T>
bool operator!=(const typename LList<T>::ConstIterator&, const typename LList<T>::ConstIterator&);
/*******************************************/

//  nested class ConstIterator for preventing changes in data pointed by iterator
//  private inheritance from class Iterator
template <class T>
class LList<T>::ConstIterator:Iterator
{
 public:
    //  ~ConstIterator();                                           //  use default
    //  ConstIterator(const ConstIterator&)                         //  use default
    //  const ConstIterator& operator=(const ConstIterator&)        //  use default

//  friend logic operators for comparing iterators
    friend bool operator==<T>(const ConstIterator&, const ConstIterator&);
    friend bool operator!=<T>(const ConstIterator&, const ConstIterator&);

    ConstIterator(const Iterator&);        //  CTOR from Iterator for implicit conversion

//  from private to public the ++ function and -- function
    using Iterator::operator++;
    using Iterator::operator--;

    const T* Get() const;
};




//---------------------------------------------------------------------------------------

//
//
//template <class T>
//LList<T>::~LList()                           //  DTOR
//{
//    ListDelete(m_list);
//}
//
//template <class T>
//LList<T>::LList()                            //  CTOR
//{
//    m_list = ListNew();
//}


//template <class T>
//    LList<T>::LList(const LList& _list)               //  copy CTOR
//    {
//
//    }
//    template <class T>
//    LList<T>& LList<T>::operator=(const LList& _list)    //  Assigment operator
//    {
//
//    }
//
//template <class T>
//        Iterator& LList<T>::Iterator::operator++()
//        {
//
//        }
//
//    //    template <class T>
//      //  Iterator& Iterator::operator--();
//template <class T>
//        T*  LList<T>::Iterator::Get() const                            //  Get also from const Iterator
//        {
//
//        }
//        template <class T>
//        bool LList<T>::Iterator::operator==(const Iterator&) const;
//        bool Iterator::operator!=(const Iterator&) const;
//
//
//        Iterator::Iterator(ListIter);     //  private CTOR from ListIter. can only initalize in Begin() or End() methods of LList.
//
//
//
//        ConstIterator::ConstIterator(Iterator);        //  CTOR from Iterator
//        ConstIterator& ConstIterator::operator++();
//        ConstIterator& ConstIterator::operator--();
//
//
//        const T* const  ConstIterator::Get() const;
//        bool ConstIterator::operator==(const ConstIterator&) const;
//        bool ConstIterator::operator!=(const ConstIterator&) const;
//
//
//
//    ConstIterator Begin() const;        //  for const list return ConstIterator for not changing data
//    ConstIterator End()   const;
//
//    Iterator    Begin();
//    Iterator    End();
//    ConstIterator    Insert(ConstIterator , const T*);
//    ConstIterator    Remove(ConstIterator);
//    Iterator    Insert(Iterator , const T*);
//    Iterator    Remove(Iterator);
//    bool        IsEmpty() const;    //  relevant also for const List

#endif  //  __LLIST_H__
